<?php

/**
 * 浙江泉邦仓 SDK
 * @author chenyun
 */

namespace App\Service\VendorClient\Shopquanbang;
use App\Service\Code\Normal;
use App\Service\TaskServer\TaskWorker;
use Service\AppService\IdService;
use Hyperf\Utils\WaitGroup;
use App\Model\PssModel\ServiceConfig;

class ShopquanbangApiClient
{
    private $account  = 'Shopquanbang';
    protected $config;
    
    /**
     * 初始参数
     * @param obj $collection
     */
    public function __construct( $apiBody = [] ) 
    {
        $this->config = $apiBody;
    }
    
    /**
     * 创建订单
     */
    public function createOrder( $params = [] ) 
    {   
        ini_set('serialize_precision', 16);
        
        if( empty($params['supplierOrder']) || empty($params['orderGoods']) || empty($params['order']) || empty($params['binfo']) ) {
            return Normal::returnCode(Normal::FAIL,"except param supplierOrder or orderGoods or order or binfo");
        }
        //组装订单参数
        $orderInfo = $params['supplierOrder'];
        $order     = $params['order'];
        $binfo     = $params['binfo'];

        //运费
        $deliver_money  = $orderInfo['deliver_money'];
        //商品下单组
        $GoodsListXml = '';
        $productAmt     = $TaxAmt = 0 ;
        foreach ($params['orderGoods'] as $key => $item ) 
        {
            //卖价
            $price              = $item['price'];
            //商品购买规格数量
            $spec_num           = $item['spec_num'];
            //商品购买数量(下单数量 X 起售数量)
            $quantity           = $item['quantity'];
            //实际购买数量          
            $buyAcount          = $spec_num * $quantity ;
            //如果商品除不尽，得多取以为，减去实际金额为折扣，折扣不能为负数
            if( $key == 0 ) {
                $singleDeliveryMoney = bcdiv((string)$deliver_money,(string)$quantity,3);
                $singleDeliveryMoney = bcmul((string)$singleDeliveryMoney,(string)100,1);
                $singleDeliveryMoney = bcdiv((string)ceil($singleDeliveryMoney), (string)100,2);
                $price               = bcadd((string)$price, (string)$singleDeliveryMoney,2);
            }
            //单个商品价格
            $singleGoodsPrice   = bcdiv((string)$price, (string)$spec_num,3);
            $singleGoodsPrice   = ceil(bcmul((string)$singleGoodsPrice,(string)'100',1));
            $singleGoodsPrice   = bcdiv((string)$singleGoodsPrice,'100',2);
            $totalGoods         = bcmul((string)$singleGoodsPrice,(string)$buyAcount,2);

            //含税税率
            $tax_rate           = bcadd('1', (string)$item['tax_rate'],4);
            
            //不含税价格
            $not_tax_price      = bcdiv((string)$singleGoodsPrice, (string)$tax_rate,3);
            // echo "含税税率:".$tax_rate."不含税价格：".$not_tax_price;
            $not_tax_price      = ceil(bcmul((string)$not_tax_price,(string)'100',1));
            // echo "含税税率:".$tax_rate."不含税价格：".$not_tax_price;
            $not_tax_price      = bcdiv((string)$not_tax_price,'100',2);
            
            //税金
            $singleGoodsTax     = bcsub((string)$singleGoodsPrice, (string)$not_tax_price,3);
            
            //单个商品总税金
            $totalGoodsTax  = bcmul((string)$singleGoodsTax,(string)$buyAcount,2);
            
            //单个商品总不含税价格
            $totalGoods     = bcmul((string)$not_tax_price,(string)$buyAcount,2);
            
            //商品组
            $GoodsListXml .= $this->arrToXml([
                'Goods'    => $this->arrToXml([
                    'GoodsSerial'   => $item['supplier_skucode'],
                    'GoodsPayPrice' => $totalGoods,
                    'GoodsNum'      => $buyAcount,
                ])
            ]);
            $productAmt = bcadd((string)$productAmt,(string)$totalGoods,2);
            $TaxAmt = bcadd((string)$TaxAmt,(string)$totalGoodsTax,2);
        }

        //实际下单金额
        $real_total_money = $orderInfo['real_total_money'];
        //订单总金额 = 含税商品总金额 + 运费 - 优惠金额
        $ActualPaidAmt = bcadd((string)$productAmt,(string)$TaxAmt,2);
        //优惠金额
        $discount_money = bcsub((string)$ActualPaidAmt,$real_total_money,2);
        //下单支付的时候支付信息
        $apply_extends  = @json_decode($orderInfo['apply_extends'],true);
        //支付时间
        $payTime        = empty($order['payTime']) ? $orderInfo['pay_time'] :$order['payTime'];
        //支付时间
        $pay_time       = $payTime ? $payTime : time();
        $pay_time       = date('Y-m-d H:i:s',$pay_time);
        //支付流水号
        $pay_sn         = $order['paySerial']??$orderInfo['pay_sn'];
        //获取上游供应商支付方式路由
        $payCommanyCode = $apply_extends['payCommanyCode'] ?? '';
        $PayCompanyCode = $order['payCommanyCode'] ? $order['payCommanyCode'] : $payCommanyCode;
        $pay_value      = ServiceConfig::instance()->getConfigByEventsValue($this->account, ServiceConfig::TYPE_PAY, $PayCompanyCode);
        if (empty($pay_value)) {
            return Normal::returnCode(Normal::FAIL, "支付公司编码：【{$PayCompanyCode}】未映射，请联系管理员处理");
        }
        
        //支付信息
        $PayInfo= [
            'PayCompanyCode' => $pay_value,
            'PayCode'        => $pay_sn,
            'PurchaserId'    => $orderInfo['buyer_phone'],
            'PurchaserName'  => $orderInfo['buyer_realname'],
            'PurchaserAddr'  => $orderInfo['receive_address'],
            'PurchaserPhone' => $orderInfo['buyer_phone'],
            'PayIdentity'    => $orderInfo['buyer_idcard'],
            'PayTime'        => $pay_time,
        ];
        
        $data=[
            'OrderFrom'         => $this->config["OrderFrom"],
            'ReciverName'       => $orderInfo['receive_name'],
            'ReciverAddress'    => $orderInfo['receive_address'],
            'ReciverPhone'      => $orderInfo['recveive_phone'],
            'ReciverDistrict'   => $orderInfo['district'],
            'ReciverCity'       => $orderInfo['city'],
            'ReciverState'      => $orderInfo['province'],
            'ReciverCountryname'=> "中国",
            'OrderMessage'      => $orderInfo['order_remark'] ? $orderInfo['order_remark'] : "",
            'HouseId'           => $this->config["HouseId"],
            'ShippingExpressId' => $this->config["ShippingExpressId"],
            'ShippingFee'       => $deliver_money,
            'OrderAmount'       => $real_total_money,
            'TaxAmount'         => $TaxAmt,
            'DiscountAmount'    => $discount_money,
            'GoodsList'         => $GoodsListXml,
            'CustomerCode'      => $orderInfo['supplier_dsn'],
            'SendType'          => $this->config["SendType"],
            'PayInfo'           => $this->arrToXml($PayInfo),
            'CustomsID'         => $this->config["CustomsID"],
            'MD5Key'            => $this->config["ApiSecret"],
        ];
        //需要加密的字段
        $key = "AddOrder". $data['CustomerCode'];
        $data['MD5Key'] = $this->_getApiMd5Value($key);
       // $data['MD5Key'] = "ec73ee3680e718a867dc70c895accf7d1684822209";
        $xml_data_xml = '<?xml version="1.0" encoding="utf-8"?>' .
                '<OmsList UserName="' . $this->config["UserName"] . '">' .
                '<Oms BusinessLogic="AddOrder">' .$this->arrToXml($data) .
                '</Oms>' .
                '</OmsList>';
        $requestParam = [
            'method'    => 'createOrder',
            'data'      => $xml_data_xml,
        ];
        $res = $this->execute($requestParam);
        if( $res['code'] == Normal::SUC ) {
            return Normal::returnCode(Normal::SUC,"订单推送成功",[
                'thirdpart_order_sn' => $res["data"]["Order"]["OrderSn"]
            ]);
        }
        return $res;
    }
   
    /**
     * 获取取消订单
     */
    public function cancelOrder( $params = [] ) 
    {
        ini_set('serialize_precision', 16);
        if( empty($params['supplierOrder'])) {
            return Normal::returnCode(Normal::FAIL,"except param supplierOrder ");
        }
        //组装订单参数
        $orderInfo = $params['supplierOrder'];
        $data=[
            'CustomerCode'=> $orderInfo['supplier_dsn'],
        ];
        //需要加密的字段
        $key = "CancelOrder";
        $data['MD5Key'] = $this->_getApiMd5Value($key);
        $xml_data_xml = '<?xml version="1.0" encoding="utf-8"?>' .
            '<OmsList UserName="' . $this->config["UserName"] . '">' .
            '<Oms BusinessLogic="CancelOrder">' .$this->arrToXml($data) .
            '</Oms>' .
            '</OmsList>';
        $requestParam = [
            'method'    => 'orderCancel',
            'data'      => $xml_data_xml,
        ];
        return $this->execute($requestParam);
    }
    
    /**
     * 组装xml
     */
    public function arrToXml(  $params = [] )
    {
        $xml = '';
        foreach ($params as $key=>$val){
            $xml .= "<{$key}>{$val}</{$key}>";
        }
        return $xml;
    }
    /**
     * api加密返回
     * @copyright 2022-06-02, coolzbw
     */
    public function _getApiMd5Value($key) {
        //组装加密xml
        $xml_data_md5 = '<?xml version="1.0" encoding="UTF-8"?>' .
            '<MD5>' .
            '<String>' . $key . '</String>' .
            '<md5key>' . $this->config["ApiSecret"] . '</md5key>' .
            '</MD5>';
        //返回加密值
        $urlmd5=$this->config["baseurl"]."/encrypt";
        $get_xml = $this->send_curl_xml($xml_data_md5,$urlmd5);
        $xmlObj  = simplexml_load_string($get_xml,"SimpleXMLElement", LIBXML_NOCDATA);
        $jsonStr = json_encode($xmlObj);
        $resHttp = json_decode($jsonStr, true);
        return $resHttp['md5value'];
    }
    /**
     * 提交并得到返回XML
     * @copyright 2022-06-02, coolzbw
     */
    function send_curl_xml($xml_data, $url) {
        $header = array();
        $header[0] = "Accept: text/xml,application/xml,application/xhtml+xml,";
        $curl = curl_init();
        curl_setopt($curl, CURLOPT_URL, $url);
        curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
        curl_setopt($curl, CURLOPT_ENCODING, 'gzip,deflate');
        curl_setopt($curl, CURLOPT_AUTOREFERER, true);
        curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($curl, CURLOPT_TIMEOUT, 60);
        curl_setopt($curl, CURLOPT_POSTFIELDS, $xml_data);
        $response = curl_exec($curl);
        if (curl_errno($curl)) {
            print curl_error($curl);
            exit();
        }
        curl_close($curl);
        return $response;
    }
    /**
     * CURL请求
     * @param $params
     * @return mixed
     */
    public function execute( $param = [] )  
    {
        if( empty($param['data']) ) {
            return Normal::returnCode(Normal::FAIL,"数据不能为空");
        }
        $method = $param['method'];
        $url = $this->config["baseurl"];
        $parameter = [
            [
                'tag'       => $this->account.'_'.$method,
                'uid'       => IdService::instance()->getOtherID(),
                'url'       => $url,
                'data'      => $param['data'],
                'method'    => 'post',
                'format'    => 'xml',
                'header'    => [
                    "Content-Type: application/xml"
                ],
        
            ],
        ];
        $resTask = TaskWorker::instance()->addTask($parameter);
        $resTask = current($resTask);
        $res     = $resTask['response']['result']; 
        $xmlObj  = simplexml_load_string($res,"SimpleXMLElement", LIBXML_NOCDATA);
        $jsonStr = json_encode($xmlObj);
        $resHttp = json_decode($jsonStr, true);
        if( isset($resHttp['Order']) && $resHttp['Order']["Status"] == 1 ) {
            return Normal::returnCode(Normal::SUC,"操作成功",$resHttp);
        }
        
        $message = isset($resHttp['Order']) ? $resHttp['Order']["Msg"] : '请求失败';
        return Normal::returnCode(Normal::FAIL,$message);
    }
}